import { CODES, KEYS } from '../keys'
import { register } from './register'
import {
  copyTextToSystemClipboard,
  copyToClipboard,
  probablySupportsClipboardBlob,
  probablySupportsClipboardWriteText
} from '../clipboard'
import { actionDeleteSelected } from './actionDeleteSelected'
import { getSelectedElements } from '../scene/selection'
import { exportCanvas } from '../data/index'
import { getNonDeletedElements, isTextElement } from '../element'
import { t } from  '/imports/i18n'

export const actionCopy = register({
  name: 'copy',
  trackEvent: { category: 'element' },
  perform: (elements, appState, _, app) => {
    const selectedElements = getSelectedElements(elements, appState, true)

    copyToClipboard(selectedElements, appState, app.files)

    return {
      commitToHistory: false
    }
  },
  contextItemPredicate: (_elements, _appState, _appProps, app) => {
    return app.device.isMobile && !!navigator.clipboard
  },
  contextItemLabel: 'labels.copy',
  // don't supply a shortcut since we handle this conditionally via onCopy event
  keyTest: undefined
})

export const actionPaste = register({
  name: 'paste',
  trackEvent: { category: 'element' },
  perform: (_elements: any, _appStates: any, _data, app) => {
    app.pasteFromClipboard(null)
    return {
      commitToHistory: false
    }
  },
  contextItemPredicate: (_elements, _appState, _appProps, app) => {
    return app.device.isMobile && !!navigator.clipboard
  },
  contextItemLabel: 'labels.paste',
  // don't supply a shortcut since we handle this conditionally via onCopy event
  keyTest: undefined
})

export const actionCut = register({
  name: 'cut',
  trackEvent: { category: 'element' },
  perform: (elements, appState, data, app) => {
    actionCopy.perform(elements, appState, data, app)
    return actionDeleteSelected.perform(elements, appState)
  },
  contextItemPredicate: (_elements, _appState, _appProps, app) => {
    return app.device.isMobile && !!navigator.clipboard
  },
  contextItemLabel: 'labels.cut',
  keyTest: event => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.X
})

export const actionCopyAsSvg = register({
  name: 'copyAsSvg',
  trackEvent: { category: 'element' },
  perform: async (elements, appState, _data, app) => {
    if (!app.canvas) {
      return {
        commitToHistory: false
      }
    }
    const selectedElements = getSelectedElements(getNonDeletedElements(elements), appState, true)
    try {
      await exportCanvas(
        'clipboard-svg',
        selectedElements.length ? selectedElements : getNonDeletedElements(elements),
        appState,
        app.files,
        appState
      )
      return {
        commitToHistory: false
      }
    } catch (error: any) {
      console.error(error)
      return {
        appState: {
          ...appState,
          errorMessage: error.message
        },
        commitToHistory: false
      }
    }
  },
  contextItemPredicate: elements => {
    return probablySupportsClipboardWriteText && elements.length > 0
  },
  contextItemLabel: 'labels.copyAsSvg'
})

export const actionCopyAsPng = register({
  name: 'copyAsPng',
  trackEvent: { category: 'element' },
  perform: async (elements, appState, _data, app) => {
    if (!app.canvas) {
      return {
        commitToHistory: false
      }
    }
    const selectedElements = getSelectedElements(getNonDeletedElements(elements), appState, true)
    try {
      await exportCanvas(
        'clipboard',
        selectedElements.length ? selectedElements : getNonDeletedElements(elements),
        appState,
        app.files,
        appState
      )
      return {
        appState: {
          ...appState,
          toast: {
            message: t('toast.copyToClipboardAsPng', {
              exportSelection: selectedElements.length ? t('toast.selection') : t('toast.canvas'),
              exportColorScheme: appState.exportWithDarkMode
                ? t('buttons.darkMode')
                : t('buttons.lightMode')
            })
          }
        },
        commitToHistory: false
      }
    } catch (error: any) {
      console.error(error)
      return {
        appState: {
          ...appState,
          errorMessage: error.message
        },
        commitToHistory: false
      }
    }
  },
  contextItemPredicate: elements => {
    return probablySupportsClipboardBlob && elements.length > 0
  },
  contextItemLabel: 'labels.copyAsPng',
  keyTest: event => event.code === CODES.C && event.altKey && event.shiftKey
})

export const copyText = register({
  name: 'copyText',
  trackEvent: { category: 'element' },
  perform: (elements, appState) => {
    const selectedElements = getSelectedElements(getNonDeletedElements(elements), appState, true)

    const text = selectedElements
      .reduce((acc: string[], element) => {
        if (isTextElement(element)) {
          acc.push(element.text)
        }
        return acc
      }, [])
      .join('\n\n')
    copyTextToSystemClipboard(text)
    return {
      commitToHistory: false
    }
  },
  contextItemPredicate: (elements, appState) => {
    return (
      probablySupportsClipboardWriteText &&
      getSelectedElements(elements, appState, true).some(isTextElement)
    )
  },
  contextItemLabel: 'labels.copyText'
})
